//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
/**
 * @addtogroup FPDFAPI
 * @{
 */

/**
 * @file
 * @brief PDF Page Object Classes
 */
//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FPDF_PAGEOBJ_H_
#define _FPDF_PAGEOBJ_H_

#ifndef _FPDF_RESOURCE_
#include "fpdf_resource.h"
#endif

#ifndef _FX_GE_H_
#include "../fxge/fx_ge.h"
#endif
//<<<+++OPENSOURCE_MUST_END

// classes defined in this header
class CPDF_Path;
class CPDF_ClipPathData;
class CPDF_ClipPath;
class CPDF_ColorStateData;
class CPDF_ColorState;
class CPDF_GraphState;
class CPDF_TextStateData;
class CPDF_TextState;
class CPDF_GeneralStateData;
class CPDF_GeneralState;
class CPDF_ContentMarkItem;
class CPDF_ContentMark;
class CPDF_GraphicStates;
class CPDF_PageObject;
class CPDF_TextObject;
class CPDF_PathObject;
class CPDF_ImageObject;
class CPDF_ShadingObject;
class CPDF_FormObject;
class CPDF_InlineImages;

/** @brief For backward compatibility. */
typedef CFX_PathData CPDF_PathData;

/** @brief PDF path class. */
class CPDF_Path : public CFX_CountRef<CFX_PathData>
{
public:
	/**
	 * @name Access path data
	 */
	/*@{*/
	
	/** Get the point count int the path. */
	int					GetPointCount() { return m_pObject->m_PointCount; }
	/**
	 * Get the flag of specified path point.
	 *
	 * @param[in] index		Specifies the zero-based index of path point in the path.
	 * @return The flag of specified path point.
	 */
	int					GetFlag(int index) { return m_pObject->m_pPoints[index].m_Flag; }
	/**
	 * Get the x-coordinate of specified path point.
	 *
	 * @param[in] index		Specifies the zero-based index of path point in the path.
	 * @return The x-coordinate of specified path point.
	 */
	FX_FLOAT			GetPointX(int index) { return m_pObject->m_pPoints[index].m_PointX; }
	/**
	 * Get the y-coordinate of specified path point.
	 *
	 * @param[in] index		Specifies the zero-based index of path point in the path.
	 * @return The y-coordinate of specified path point.
	 */
	FX_FLOAT			GetPointY(int index) { return m_pObject->m_pPoints[index].m_PointY; }

	/*@}*/

	/**
	 * @name Access points
	 */
	/*@{*/

	/** Get the path points in the path. */
	FX_PATHPOINT*		GetPoints() { return m_pObject->m_pPoints; }

	/*@}*/

	/**
	 * Get bounding box of all control points.
	 * The result can be used as the bounding box of the whole filled path.
	 * However, when path is stroked using geometry pen, the actual bounding box can be much larger.
	 */
	CFX_FloatRect		GetBoundingBox() const { return m_pObject->GetBoundingBox(); }

	/**
	 * Calculate bounding box (guaranteed to contain all path, may be larger) for stroked path. 
	 *
	 * @param[in] line_width	The line width used in stroking.
	 * @param[in] miter_limit	The miter limit value for line joint in stroking.	 
	 */
	CFX_FloatRect		GetBoundingBox(FX_FLOAT line_width, FX_FLOAT miter_limit) const
	{ return m_pObject->GetBoundingBox(line_width, miter_limit); }

	/**
	 * Transform this path.
	 *
	 * @param[in] pMatrix		The input matrix used to transform.
	 */
	void				Transform(const CFX_AffineMatrix* pMatrix) { GetModify()->Transform(pMatrix); }

	/**
	 * Append a path. Optionally a matrix can be specified to transform the source path before appending. 
	 *
	 * @param[in] src			The source path.
	 * @param[in] pMatrix		The specified matrix. NULL means no transformation.
	 */
	void				Append(CPDF_Path src, const CFX_AffineMatrix* pMatrix)
	{ m_pObject->Append(src.m_pObject, pMatrix); }
	/**
	 * Append a rectangle.
	 *
	 * @param[in] left			The x-coordinate of the left-bottom corner.
	 * @param[in] bottom		The y-coordinate of the left-bottom corner.
	 * @param[in] right			The x-coordinate of the right-top corner.
	 * @param[in] top			The y-coordinate of the right-top corner.
	 */
	void				AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top)
	{ m_pObject->AppendRect(left, bottom, right, top); }

	/** Is the path actually a rectangle ? */
	FX_BOOL				IsRect() const { return m_pObject->IsRect(); }
};

/** @brief PDF clip path data class. */
class CPDF_ClipPathData : public CFX_Object
{
public:
	/** Construct an empty clip path data. */
	CPDF_ClipPathData();
	/** Copy constructor. */
	CPDF_ClipPathData(const CPDF_ClipPathData&);
	/** The destructor. */
	~CPDF_ClipPathData();

	/**
	 * Estimate the count of path and text in the clip path data, and allocate the memory.
	 *
	 * @param[in] path_count	The estimated count of path in the clip path data.
	 * @param[in] text_count	The estimated count of text object in the clip path data.
	 */
	void				SetCount(int path_count, int text_count);

public:
	/** The count of paths. */
	int					m_PathCount;
	/** The path array. */
	CPDF_Path*			m_pPathList;
	/** The path flags array. #FXFILL_WINDING or #FXFILL_ALTERNATE. */
	FX_BYTE*			m_pTypeList; 
	/** The count of text objects. */
	int					m_TextCount;
	/** The text object array. */
	CPDF_TextObject**	m_pTextList;
};

/** @brief PDF clip path class. */
class CPDF_ClipPath : public CFX_CountRef<CPDF_ClipPathData>
{
public:
	/** Get the count of paths in the clip path. */
	FX_DWORD			GetPathCount() const { return m_pObject->m_PathCount; }
	/**
	 * Get a path.
	 *
	 * @param[in] i		Specifies the zero-based path index in the clip path.
	 * @return A path.
	 */
	CPDF_Path			GetPath(int i) const { return m_pObject->m_pPathList[i]; }
	/**
	 * Get the clip type of specified path.
	 *
	 * @param[in] i		Specifies the zero-based path index in the clip path.
	 * @return The clip type of specified path.
	 */
	int					GetClipType(int i) const { return m_pObject->m_pTypeList[i]; }
	/** Get the count of text objects in the clip path. */
	FX_DWORD			GetTextCount() const { return m_pObject->m_TextCount; }
	/**
	 * Get a text object.
	 *
	 * @param[in] i		Specifies the zero-based text object index in the clip path.
	 * @return A text object.
	 */
	CPDF_TextObject*	GetText(int i) const { return m_pObject->m_pTextList[i]; }

	/** Get the clip box of the clip path. */
	CFX_FloatRect		GetClipBox() const;

	/**
	 * Append a clipping path.
	 *
	 * @param[in] path			The input clipping path.
	 * @param[in] type			The clip type of the input clipping path.
	 * @param[in] bAutoMerge	Whether to merge the clipping path automatically.
	 */
	void				AppendPath(CPDF_Path path, int type, FX_BOOL bAutoMerge);
    
	/**
	 * Remove a path from path list.
	 *
	 * @param[in] layer_index	The path index to remove.
	 */
	void				DeletePath(int layer_index);
    
	/**
	 * Append clipping text objects.
	 *
	 * @param[in] pTexts		Pointer to clipping text objects to append.
	 * @param[in] count			The count of clipping text objects to append.
	 */
	void				AppendTexts(CPDF_TextObject** pTexts, int count);
    
    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/**
	 * Delete a clipping text object. 
	 *
	 * @param[in] pTextObj		Pointer to clipping text object to delete.
	 *
	 * @note If success, the text object can not be used.
	 */
	FX_BOOL				DeleteText(CPDF_TextObject* pTextObj);
    //<<<+++OPENSOURCE_END
	/**
	 * Transform the clip path. Rotate, shear, or move clip path.
	 *
	 * @param[in] matrix		The matrix used to transform.
	 */
	void				Transform(const CFX_AffineMatrix& matrix);
};

/**
 * @brief PDF color state data class.
 *
 * 2006-10-03: Currently CPDF_ColorStateData is the only class that support NULL flags for all its members.
 */
class CPDF_ColorStateData : public CFX_Object
{
public:
	/** Default constructor will set colors to NULL. */
	CPDF_ColorStateData() {}
	/** Copy constructor. */
	CPDF_ColorStateData(const CPDF_ColorStateData& src);

	/** Set the color state data to default. */
	void				Default();

	/** The filling color. */
	CPDF_Color			m_FillColor;
	/** The filling RGB color. Windows RGB format. -1 for no color (like Separation None). */
	FX_DWORD			m_FillRGB;
	/** The stroking color. */
	CPDF_Color			m_StrokeColor;
	/** The stroking RGB color. Windows RGB format. -1 for no color (like Separation None). */
	FX_DWORD			m_StrokeRGB;
};

/** @brief PDF color state class. */
class CPDF_ColorState : public CFX_CountRef<CPDF_ColorStateData>
{
public:
	/** Get the filling color. */
	CPDF_Color*			GetFillColor() const { return m_pObject ? &m_pObject->m_FillColor : NULL; }
	/** Get the stroking color. */
	CPDF_Color*			GetStrokeColor() const { return m_pObject ? &m_pObject->m_StrokeColor : NULL; }

	/**
	 * Set the filling normal color.
	 *
	 * @param[in] pCS		The color space of the filling color.
	 * @param[in] pValue	The color component values in the specified color space.
	 * @param[in] nValues	Number of color component values.
	 */
	void				SetFillColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues);
	/**
	 * Set the stroking normal color.
	 *
	 * @param[in] pCS		The color space of the stroking color.
	 * @param[in] pValue	The color component values in the specified color space.
	 * @param[in] nValues	Number of color component values.
	 */
	void				SetStrokeColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues);

	/**
	 * Set the filling pattern color.
	 *
	 * @param[in] pattern	The input pattern.
	 * @param[in] pValue	The input parameters for the pattern color.
	 * @param[in] nValues	The count of the input parameters.
	 */
	void				SetFillPattern(CPDF_Pattern* pattern, FX_FLOAT* pValue, int nValues);
	/**
	 * Set the stroking pattern color.
	 *
	 * @param[in] pattern	The input pattern.
	 * @param[in] pValue	The input parameters for the pattern color.
	 * @param[in] nValues	The count of the input parameters.
	 */
	void				SetStrokePattern(CPDF_Pattern* pattern, FX_FLOAT* pValue, int nValues);

private:
	void				SetColor(CPDF_Color& color, FX_DWORD& rgb, CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues);
#if !defined(_FXM_OPENSOURCE_)
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	friend class CPDF_PageObjectsCache;
	//<<<+++OPENSOURCE_END
#endif
};

/** @brief For backward compatibility only. */
typedef CFX_GraphStateData CPDF_GraphStateData;

/**
 * @brief PDF graph state class.
 *
 * No derived member defined now. Please look at CFX_CountRef template for base class members.
 */
class CPDF_GraphState : public CFX_CountRef<CFX_GraphStateData>
{
public:
};

/** @brief PDF text state data class. */
class CPDF_TextStateData : public CFX_Object
{
public:
	/** Default constructor. */
	CPDF_TextStateData();
	/** Copy constructor. */
	CPDF_TextStateData(const CPDF_TextStateData& src);
	/**Destructor. */
	~CPDF_TextStateData();

	/** The font. */
	CPDF_Font*			m_pFont;
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
#ifdef _FPDFAPI_CACHEPOINTER_
	/** The font pointer. */
	CPDF_Font**			m_pPtrFont;
#endif
//<<<+++OPENSOURCE_END
	/** The font size. */
	FX_FLOAT			m_FontSize;
	/** The character space. */
	FX_FLOAT			m_CharSpace;
	/** The word space. */
	FX_FLOAT			m_WordSpace;
	/** The text transformation matrix. */
	FX_FLOAT		m_Matrix[4];
	/** The text mode. */
	int					m_TextMode;
	/** CTM for stroking purpose. */
	FX_FLOAT		m_CTM[4];
};

/** @brief PDF text state class. */
class CPDF_TextState : public CFX_CountRef<CPDF_TextStateData>
{
public:
	/** Get the font. */
	CPDF_Font*			GetFont() const { return m_pObject->m_pFont; }
	/**
	 * Set the font.
	 *
	 * @param[in] pFont		The input font. 
	 */
	void				SetFont(CPDF_Font* pFont);
	/** Get the font size. */
	FX_FLOAT			GetFontSize() const { return m_pObject->m_FontSize; }
	/** Get the text transformation matrix. */
	FX_FLOAT*			GetMatrix() const { return m_pObject->m_Matrix; }

	/**
	 * @name Derived information from text matrix.
	 */
	/*@{*/

	/** Get the vertical size in device units. */
	FX_FLOAT			GetFontSizeV() const;
	/** Get the horizontal size in device units. */
	FX_FLOAT			GetFontSizeH() const;
	/** Get the angle between device space X-axis and text baseline. In radians. */
	FX_FLOAT			GetBaselineAngle() const;
	/** Get the angle that text space Y-axis shears in device space. In radians. */
	FX_FLOAT			GetShearAngle() const;

	/*@}*/

};

class CPDF_TransferFunc;

/** @brief PDF general state data class. */
class CPDF_GeneralStateData : public CFX_Object
{
public:
	/** Default constructor. */
	CPDF_GeneralStateData();
	/** Copy constructor. */
	CPDF_GeneralStateData(const CPDF_GeneralStateData& src);
	~CPDF_GeneralStateData();

	/**
	 * Set the current blend mode to be used in the transparent imaging model.
	 *
	 * @param[in] blend_mode	The new blend mode.
	 */
	void				SetBlendMode(FX_BSTR blend_mode);

	/** The current blend mode name. */
	char				m_BlendMode[16];
	/** The current blend mode to be used in the transparent imaging model. */
	int					m_BlendType;
	/** The current soft mask, specifying the mask shape or mask opacity values to be used in the transparent imaging model. */ 
	CPDF_Object*		m_pSoftMask;
	/** The matrix of the current soft mask. */
	FX_FLOAT			m_SMaskMatrix[6];
	/**
	 * The current stroking alpha constant, specifying the constant shape or constant opacity value to be used for 
	 * stroking operations in the transparent imaging model.
	 */
	FX_FLOAT			m_StrokeAlpha;
	/** Same as CPDF_GeneralStateData::m_StrokeAlpha, but for nonstroking operations. */ 
	FX_FLOAT			m_FillAlpha;
	/** The transfer function object. */
	CPDF_Object*		m_pTR;
	/** The transfer function. */
	CPDF_TransferFunc*	m_pTransferFunc;
	/** The current matrix. */
	CFX_Matrix			m_Matrix;
#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
	/** The rendering intent. */
	int					m_RenderIntent;
	/** Whether to apply automatic stroke adjustment. */
	FX_BOOL				m_StrokeAdjust;
	/** Whether the current soft mask and alpha constant are to be interpreted as shape values (true) or opacity values (false). */ 
	FX_BOOL				m_AlphaSource;
	/** It determines the behavior of overlapping glyphs within a text object in the transparent imaging model. */
	FX_BOOL				m_TextKnockout;
	/** A flag specifying whether to apply overprint for stroking. */
	FX_BOOL				m_StrokeOP;
	/** A flag specifying whether to apply overprint for filling. */
	FX_BOOL				m_FillOP;
	/** The overprint mode. */
	int					m_OPMode;
	/** The black-generation function. */
	CPDF_Object*		m_pBG;
	/** The undercolor-removal function. */
	CPDF_Object*		m_pUCR;
	/** The halftone object, denoting the halftone that was in effect at the start of the page. */ 
	CPDF_Object*		m_pHT;
	/** The flatness tolerance. */
	FX_FLOAT			m_Flatness;
	/** The smoothness tolerance. */
	FX_FLOAT			m_Smoothness;
#endif
};

/** @brief PDF general state class. */
class CPDF_GeneralState : public CFX_CountRef<CPDF_GeneralStateData>
{
public:
	/**
	 * Set the rendering intent.
	 *
	 * @param[in] ri	The input rendering intent.
	 */
	void				SetRenderIntent(const CFX_ByteString& ri);
	/** Get the blend mode. */
	int					GetBlendType() const { return m_pObject ? m_pObject->m_BlendType : FXDIB_BLEND_NORMAL; }
	/**
	 * Get the current filling or stroking alpha constant.
	 *
	 * @param[in] bStroke	Whether to get the current stroking alpha constant.
	 */
	int					GetAlpha(FX_BOOL bStroke) const 
	{ return m_pObject ? FXSYS_round((bStroke ? m_pObject->m_StrokeAlpha : m_pObject->m_FillAlpha)*255) : 255; }
};

/** @brief PDF content mark item class. */
class CPDF_ContentMarkItem : public CFX_Object
{
public:
	/** @brief Parameter type enumeration of content mark item. */
	typedef enum {
		None,				/**< None parameters. */
		PropertiesDict,		/**< The dictionary defined by named resource in the Properties sub-dictionary of the current resource dictionary. */
		DirectDict,			/**< The dictionary may be written inline in the content stream as a direct object. */
		MCID				/**< (discard)The dictionary contains an MCID entry, which is an integer marked-content identifier
							that uniquely identifies the marked-content sequence within its content stream. */
	} ParamType;

	/** Default constructor. */
	CPDF_ContentMarkItem();
	/** Copy constructor. */
	CPDF_ContentMarkItem(const CPDF_ContentMarkItem& src);
	/** The destructor. */
	~CPDF_ContentMarkItem();

	/** Get the name(tag) of the content mark item. */ 
	inline const CFX_ByteString&	GetName() const { return m_MarkName; }
	/** Get the parameter type of the content mark item. */
	inline ParamType	GetParamType() const { return m_ParamType; }
	/** Get the parameter of the content mark item. */
	inline void*		GetParam() const { return m_pParam; }
	/** Has MCID entry. */
	inline FX_BOOL		HasMCID() const;

	/**
	 * Set the name(tag) of the content mark item.
	 *
	 * @param[in] name		The input new name(tag).
	 */
	inline void			SetName(const CFX_ByteString& name) { m_MarkName = name; }
	/**
	 * Set the parameter of the content mark item.
	 *
	 * @param[in] type		The input new parameter type.
	 * @param[in] param		The input new parameter.
	 */
	inline void			SetParam(ParamType type, void* param) { m_ParamType = type; m_pParam = param; }

private:
	/** The name(tag). */
	CFX_ByteString		m_MarkName;
	/** The parameter type. */
	ParamType			m_ParamType;
	/** The parameter. NULL, dictionary, or MCID. */
	void*				m_pParam;
};

/** @brief PDF content mark data class. */
class CPDF_ContentMarkData : public CFX_Object
{
public:
	/** Default constructor. */
	CPDF_ContentMarkData() { }
	/** Copy constructor. */
	CPDF_ContentMarkData(const CPDF_ContentMarkData& src);

	/** Get the count of content mark items in the content mark data. */
	inline int			CountItems() const { return m_Marks.GetSize(); }
	/**
	 * Get a content mark item.
	 *
	 * @param[in] index		The zero-based content mark item index in the content mark data.
	 * @return A content mark item.
	 */
	inline CPDF_ContentMarkItem&	GetItem(int index) const { return m_Marks[index]; }

	/** Get the marked-content identifier. */
	int					GetMCID() const;

	/**
	 * Add a content mark item.
	 *
	 * @param[in] name				The input name(tag) of the content mark item.
	 * @param[in] pDict				The parameter(attributes) dictionary of the content mark item.
	 * @param[in] bDictNeedClone	Whether the input dictionary must be copied or not.
	 */
	void				AddMark(const CFX_ByteString& name, CPDF_Dictionary* pDict, FX_BOOL bDictNeedClone);
    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/**
	 * Delete a content mark item.
	 *
	 * @param[in] name			The name(tag) of the content mark item.
	 */
	void				DeleteMark(FX_BSTR name);
    //<<<+++OPENSOURCE_END
	/** Delete the last content mark item. */
	void				DeleteLastMark();

protected:
	/** The content mark item array. */
	CFX_ObjectArray<CPDF_ContentMarkItem>	m_Marks;
};

/** @brief PDF content mark class. */
class CPDF_ContentMark : public CFX_CountRef<CPDF_ContentMarkData>
{
public:
	/** Get the marked-content identifier. */
	int					GetMCID() const { return m_pObject ? m_pObject->GetMCID() : -1; }

	/**
	 * Check whether the content mark has a specified content mark item.
	 *
	 * @param[in] mark		The name(tag) of the content mark item.
	 * @return Non-zero means it has, otherwise it has not.
	 */
	FX_BOOL				HasMark(FX_BSTR mark) const;
	/**
	 * Lookup a content mark item.
	 *
	 * @param[in] mark		The name(tag) of the content mark item.
	 * @param[out] pDict	It receives the parameter(attributes) dictionary.
	 * @return Non-zero means found one, otherwise found none.
	 */
	FX_BOOL				LookupMark(FX_BSTR mark, CPDF_Dictionary*& pDict) const;
};

/**
 * @name Displayable objects
 */
/*@{*/

/** @brief text object. */
#define PDFPAGE_TEXT		1
/** @brief path object. */
#define PDFPAGE_PATH		2
/** @brief image object. */
#define PDFPAGE_IMAGE		3
/** @brief shading object. */
#define PDFPAGE_SHADING		4
/** @brief form object. */
#define PDFPAGE_FORM		5
/** @brief inline image object. Inline image section. FOR EMBEDDED SYSTEM ONLY*/
#define PDFPAGE_INLINES		6

/*@}*/

/** @brief PDF graphic states class. A structure including all applicable graphic states. */
class CPDF_GraphicStates : public CFX_Object
{
public:
	/**
	 * Copy from another graphic states.
	 *
	 * @param[in] src	The input graphic states.
	 */
	void				CopyStates(const CPDF_GraphicStates& src);
	/** Set all graphic states to default. */
	void				DefaultStates();

	/** The clip path state. for all objects. */  
	CPDF_ClipPath		m_ClipPath;
	/** The graph state. for graphs and type3 font or stroke texts. */
	CPDF_GraphState		m_GraphState;
	/** The color state. for texts, graphs and uncolored images. */
	CPDF_ColorState		m_ColorState;
	/** The text state. for texts only. */
	CPDF_TextState		m_TextState;
	/** The general state. for all objects. */
	CPDF_GeneralState	m_GeneralState;
};

/** @brief PDF page object class. Describing displayable objects within page content. */
class CPDF_PageObject : public CPDF_GraphicStates
{
public:
	/**
	 * Create a page object with specified type.
	 *
	 * @param[in] type		The input page object type.
	 * @return A page object.
	 */
	static CPDF_PageObject* Create(int type);
	/** Destroy an object. */
	void				Release();
	/** Clone an page object. */
	CPDF_PageObject*	Clone() const;
	/**
	 * Copy from another page object.
	 *
	 * @param[in] pSrcObject	The source page object.
	 */
	void				Copy(const CPDF_PageObject* pSrcObject);

	/**
	 * Transform the page object. Rotate, shear, or move object.
	 *
	 * @param[in] matrix	The transform matrix used to transform. 
	 */
	virtual void		Transform(const CFX_AffineMatrix& matrix) = 0;
    
	/**
	 * @name Clipping path operations.
	 */
	/*@{*/

	/** Remove clipping path of the object. */
	void				RemoveClipPath();
	/**
	 * Append a clipping path.
	 *
	 * @param[in] path			The input clipping path.
	 * @param[in] type			The clip type of the input clipping path.
	 * @param[in] bAutoMerge	Whether to merge the clipping path automatically.
	 */
	void				AppendClipPath(CPDF_Path path, int type, FX_BOOL bAutoMerge);
	/**
	 * Copy clipping path from another object.
	 *
	 * @param[in] pObj			The source page object.
	 */
	void				CopyClipPath(CPDF_PageObject* pObj);
    
	/**
	 * Transform the clip path. Rotate, shear, or move clip path.
	 *
	 * @param[in] matrix		The matrix used to transform.
	 */
	void				TransformClipPath(CFX_AffineMatrix& matrix);

	/** 
	 * Transform the general state matrix.
	 *
	 * @param[in] matrix		The matrix used to transform.
	 */
	void				TransformGeneralState(CFX_AffineMatrix& matrix);
	/*@}*/

	/**
	 * Set the color state.
	 *
	 * @param[in] state			The new color state.
	 */
	void				SetColorState(CPDF_ColorState state) { m_ColorState = state; }

	/**
	 * Get the bounding box of the page object, optionally with a transform matrix.
	 *
	 * @param[in] pMatrix		The input transform matrix.
	 */
	FX_RECT				GetBBox(const CFX_AffineMatrix* pMatrix) const;

	/** The page object type. */
	int					m_Type;
	/** The x-coordinate of the left-bottom corner of the bounding box in page space. */
	FX_FLOAT			m_Left;
	/** The x-coordinate of the right-top corner of the bounding box in page space. */
	FX_FLOAT			m_Right;
	/** The y-coordinate of the right-top corner of the bounding box in page space. */
	FX_FLOAT			m_Top;
	/** The y-coordinate of the left-bottom corner of the bounding box in page space. */
	FX_FLOAT			m_Bottom;
	/** The content mark. */
	CPDF_ContentMark	m_ContentMark;

protected:
	/**
	 * Copy data from another page object.
	 *
	 * @param[in] pSrcObject	The source page object.
	 */
	virtual void		CopyData(const CPDF_PageObject* pSrcObject) {}
	/** Recalculate the bounding box. */
	void				RecalcBBox();

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	friend class CPDF_PageObjectsCache;
//<<<+++OPENSOURCE_END
#endif

	/** The default constructor. */
	CPDF_PageObject() {}
	/** The destructor. */
	virtual ~CPDF_PageObject() {}
};

/** @brief PDF text object item structure. */
struct CPDF_TextObjectItem : public CFX_Object
{
	/** The character code. -1 (0xffffffff) for spacing. */
	FX_DWORD			m_CharCode;
	/** X origin in text space, or the spacing. */
	FX_FLOAT			m_OriginX;
	/** Y origin in text space. */
	FX_FLOAT			m_OriginY;
};

/** @brief PDF text object class. */
class CPDF_TextObject : public CPDF_PageObject
{
public:
	/** Default constructor. */
	CPDF_TextObject();
	/** The destructor. */
	virtual ~CPDF_TextObject();

	/** Get the count of text object items. */ 
	int					CountItems() const { return m_nChars; }
	/**
	 * Get specified text object item information.
	 *
	 * @param[in] index		Specify zero-based item index in the text object.
	 * @param[out] pInfo	It receives the specified text object item information.
	 */
	void				GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const;

	/** Get the count of characters in the text object. */
	int					CountChars() const;
	/**
	 * Get the information of specified character.
	 *
	 * @param[in] index			Specify zero-based character index in the text object.
	 * @param[out] charcode		It receives the character code.
	 * @param[out] kerning		It receives the kerning(x-direction only).
	 */
	void				GetCharInfo(int index, FX_DWORD& charcode, FX_FLOAT& kerning) const;
	void				GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const;

	/**
	 * Get the rect of specified character.
	 *
	 * @param[in] index			Specify zero-based character index in the text object.
	 * @param[out] rect			It receives the rect.
	 */
	void				GetCharRect(int index, CFX_FloatRect& rect) const;
	
	/** Get the width of characters. */
	FX_FLOAT			GetCharWidth(FX_DWORD charcode) const;
	FX_FLOAT			GetSpaceCharWidth() const;

	/** Get the x-coordinate of the origin in the device space. */
	FX_FLOAT			GetPosX() const { return m_PosX; }
	/** Get the y-coordinate of the origin in the device space. */
	FX_FLOAT			GetPosY() const { return m_PosY; }
	/**
	 * Get matrix from text space to object space.
	 *
	 * @param[out] pMatrix		It receives the matrix from text space to object space.
	 */
	void				GetTextMatrix(CFX_AffineMatrix* pMatrix) const;

	/** Get the font. */
	CPDF_Font*			GetFont() const { return m_TextState.GetFont(); }
	/** Get the font size. */
	FX_FLOAT			GetFontSize() const { return m_TextState.GetFontSize(); }
    
	/** Set the text object to be empty. */
	void				SetEmpty();
    
	/**
	 * Set a single text segment without any kerning inside.
	 *
	 * @param[in] text		The input text segment.
	 */
	void				SetText(const CFX_ByteString& text);

	/**
	 * Set text using segmented fashion.
	 *
	 * @param[in] pStrs			The input text segments.
	 * @param[in] pKerning		The kerning array.
	 * @param[in] nSegs			The count of text segments.
	 */
	void				SetText(CFX_ByteString* pStrs, FX_FLOAT* pKerning, int nSegs);

	/**
	 * Set text using char-kerning pair fashion.
	 *
	 * @param[in] nChars		The count of input character codes.
	 * @param[in] pCharCodes	The input character codes.
	 * @param[in] pKernings		The input kerning array.
	 */
	void				SetText(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pKernings);

	/**
	 * Set the origin position in device space.
	 *
	 * @param[in] x				The x-coordinate in device space.
	 * @param[in] y				The y-coordinate in device space. 
	 */
	void				SetPosition(FX_FLOAT x, FX_FLOAT y);
	/**
	 * Set the text state.
	 *
	 * @param[in] TextState		The new text state.
	 */
	void				SetTextState(CPDF_TextState TextState);
	virtual void		Transform(const CFX_AffineMatrix& matrix);

	/**
	 * Calculate origin positions in text space, for each character.
	 * The position array must be allocated and freed by caller. It must contain at least nChars*2 elements.
	 * For each character, the origin position (along the text baseline) and next origin position will be calculated.
	 *
	 * @param[out] pPosArray	It receives the character position array.
	 */
	void				CalcCharPos(FX_FLOAT* pPosArray) const;

	/**
	 * @name Used for archiving purpose.
	 */
	/*@{*/

	/**
	 * Set text data.
	 *
	 * @param[in] nChars			The count of characters to set.
	 * @param[in] pCharCodes		The input character codes array.
	 * @param[in] pCharPos			The input character positions array in text space.
	 * @param[in] x					The x-coordinate of the origin position, in device space.
	 * @param[in] y					The y-coordinate of the origin position, in device space.
	 */
	void				SetData(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, FX_FLOAT x, FX_FLOAT y);
	/**
	 * Get text data.
	 *
	 * @param[out] nChars			It receives the count of characters.
	 * @param[out] pCharCodes		It receives the character codes array.
	 * @param[out] pCharPos			It receives the character positions array in text space.
	 */
	void				GetData(int& nChars, FX_DWORD*& pCharCodes, FX_FLOAT*& pCharPos) 
						{ nChars = m_nChars; pCharCodes = m_pCharCodes; pCharPos = m_pCharPos; }

	/*@}*/

	/** Recalculate the position data. */
	void				RecalcPositionData() { CalcPositionData(NULL, NULL, 1); }
protected:
	virtual void		CopyData(const CPDF_PageObject* pSrcObject);

	/** The x-coordinate of the origin position, in device space. */
	FX_FLOAT			m_PosX;
	/** The y-coordinate of the origin position, in device space. */
	FX_FLOAT			m_PosY;
	/** Number of characters (NOTE: including special chars for spacing). */
	int					m_nChars;
	/**
	 * Character codes. When we have only one character, this is the charcode itself.
	 * A special charcode -1 (0xffffffff) is used for spacing flag, in this case,
	 * the corresponding char position is actually the spacing (in 1/1000 of em square).
	 */
	FX_DWORD*			m_pCharCodes;
	/**
	 * Character origin positions (on the baseline).
	 * The first character always has origin at 0, so when we have only one char,
	 * this pointer will be NULL.
	 */
	FX_FLOAT*		m_pCharPos;

	/**
	 * Set text segments.
	 *
	 * @param[in] pStrs			The input text segments.
	 * @param[in] pKerning		The kerning array.
	 * @param[in] nSegs			The count of text segments.
	 */
	void				SetSegments(const CFX_ByteString* pStrs, FX_FLOAT* pKerning, int nSegs);
	/**
	 * Calculate the position data in the text space.
	 *
	 * @param[in] pTextAdvanceX		The input advance-x array.
	 * @param[in] pTextAdvanceY		The input advance-y array.
	 * @param[in] horz_scale		The horizontal scaling.
	 */
	void				CalcPositionData(FX_FLOAT* pTextAdvanceX, FX_FLOAT* pTextAdvanceY, FX_FLOAT horz_scale, int level = 0);

	friend class		CPDF_StreamContentParser;
	friend class		CPDF_RenderStatus;
	friend class		CPDF_QuickDrawer;
	friend class		CPDF_TextRenderer;
	friend class		CTextPage;
	friend class		CPDF_ContentGenerator;
#ifndef _FXM_OPENSOURCE_
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	friend class CPDF_PageObjectsCache;
	//<<<+++OPENSOURCE_END
#endif
};

/** @brief PDF path object class. */
class CPDF_PathObject : public CPDF_PageObject
{
public:
	/** Construct an empty path object. */
	CPDF_PathObject() { m_Type = PDFPAGE_PATH; }
	/** The destructor. */
	virtual ~CPDF_PathObject() {}

	virtual void		Transform(const CFX_AffineMatrix& maxtrix);
    
	/**
	 * Set the graph state.
	 *
	 * @param[in] GraphState	The input new graph state.
	 */
	void				SetGraphState(CPDF_GraphState GraphState);

	/** The path. reference to path data. */
	CPDF_Path			m_Path;
	/** The filling mode. 0, #FXFILL_ALTERNATE, #FXFILL_WINDING. */
	int					m_FillType;
	/** Whether to stroke the path. */
	FX_BOOL				m_bStroke;
	/** The transform matrix. Matrix used to transform the path coordinates. Also used to determine line geometry. */
	CFX_AffineMatrix	m_Matrix;
	
	/** Calculate the bounding box. */
	void				CalcBoundingBox();
protected:
	virtual void		CopyData(const CPDF_PageObject* pSrcObjet);
};

/** @brief PDF image object class. */
class CPDF_ImageObject : public CPDF_PageObject
{
public:
	/** Construct an empty image object. */
	CPDF_ImageObject();
	/** The destructor. */
	virtual ~CPDF_ImageObject();

	virtual void		Transform(const CFX_AffineMatrix& matrix);

	/** The image. */
	CPDF_Image*			m_pImage;
	/** The transform matrix. */
	CFX_AffineMatrix	m_Matrix;

	/** Calculate the bounding box. */
	void				CalcBoundingBox();
private:
	virtual void		CopyData(const CPDF_PageObject* pSrcObjet);
};

/** @brief PDF shading object class. */
class CPDF_ShadingObject : public CPDF_PageObject
{
public:
	/** Construct an empty shading object. */
	CPDF_ShadingObject();
	/** The destructor. */
	virtual ~CPDF_ShadingObject();

	/** The shading. */
	CPDF_ShadingPattern*	m_pShading;
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
#ifdef _FPDFAPI_CACHEPOINTER_
	CPDF_ShadingPattern**	m_pPtrShading;
#endif
//<<<+++OPENSOURCE_END
	/** The transform matrix. the matrix from shading coordinate to device coordinate. */
	CFX_AffineMatrix	m_Matrix;
	/** The page. */
	CPDF_Page*			m_pPage;
	virtual void		Transform(const CFX_AffineMatrix& matrix);
	/** Calculate the bounding box. */
	void				CalcBoundingBox();
protected:
	virtual void		CopyData(const CPDF_PageObject* pSrcObjet);
};

/** @brief PDF form object class. */
class CPDF_FormObject : public CPDF_PageObject
{
public:
	/** Construct an empty form object. */
	CPDF_FormObject() { m_Type = PDFPAGE_FORM; m_pForm = NULL; }
	/** The destructor. */
	virtual ~CPDF_FormObject();
	virtual void		Transform(const CFX_AffineMatrix& matrix);
	/** The form. */
	CPDF_Form*			m_pForm;
	/** The transform matrix. */
	CFX_AffineMatrix	m_FormMatrix;

	/** Calculate the bounding box. */
	void				CalcBoundingBox();
protected:
	virtual void		CopyData(const CPDF_PageObject* pSrcObjet);
};

/** @brief PDF repeated inline images object class. Used on embedded platforms only. */
class CPDF_InlineImages : public CPDF_PageObject
{
public:
	/** Construct an empty repeated inline images object. */
	CPDF_InlineImages();
	/** The destructor. */
	virtual ~CPDF_InlineImages();

	/** The stream */
	CPDF_Stream*		m_pStream;
	/** The DIB bitmap. Only available after first rendered. */
	CFX_DIBitmap*		m_pBitmap;
	/** The transform matrix array. */
	CFX_ArrayTemplate<CFX_AffineMatrix>	m_Matrices;

	/**
	 * Add a transform matrix.
	 *
	 * @param[in] matrix	The input transform matrix.
	 */
	void				AddMatrix(CFX_AffineMatrix& matrix);

protected:
	virtual void		Transform(const CFX_AffineMatrix& matrix) {}
	virtual void		CopyData(const CPDF_PageObject* pSrcObjet) {}
};
//<<<+++OPENSOURCE_MUST_BEGIN
#endif	// _FPDF_PAGEOBJ_H_
//<<<+++OPENSOURCE_MUST_END
/** @} */



